/**
 * 
 */
package com.arx.script;

import com.arx.common.GlobalConsts;
import com.arx.interactive.Interactive;
import com.arx.interactive.InteractiveObject;
import com.arx.script.flyweight.ScriptObject;
import com.arx.script.flyweight.ScriptTimer;
import com.arx.time.Time;
import com.dalonedrau.pool.PooledStringBuilder;
import com.dalonedrau.pool.StringBuilderPool;

/**
 * @author Donald
 */
abstract class ScriptTimerBase extends ScriptTextBase {
	/**
	 * Gets the index system script timer associated with a specific
	 * {@link InteractiveObject} and having a specific name.
	 * @param io the {@link InteractiveObject}
	 * @param name the name
	 * @return int
	 */
	public final int ARX_SCRIPT_GetSystemIOScript(final InteractiveObject io,
			final String name) {
		int val = -1;
		if (super.getActiveTimers() > 0) {
			for (int i = 0; i < super.getMAX_TIMER_SCRIPT(); i++) {
				if (super.getScriptTimer(i) != null
						&& super.getScriptTimer(i).exists()
						&& super.getScriptTimer(i).getIo() != null
						&& super.getScriptTimer(i).getIo().equals(io)
						&& super.getScriptTimer(i).getNameAsString()
								.equalsIgnoreCase(name)) {
					val = i;
					break;
				}
			}
		}
		return val;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public final long ARX_SCRIPT_CountTimers() {
		return super.getActiveTimers();
	}
	public final void ARX_SCRIPT_Timer_Check() {
		if (super.getActiveTimers() > 0) {
			for (int i = 0; i < super.getMAX_TIMER_SCRIPT(); i++) {
				ScriptTimer st = super.getScriptTimer(i);

				if (st != null
						&& st.exists()) {
					if (st.hasFlag(1)
							&& st.getIo() != null
							&& !st.getIo().hasGameFlag(
									GlobalConsts.GFLAG_ISINTREATZONE)) {
						while (st.getTim() + st.getMsecs() < Time.getInstance()
								.getARXTime()) {
							st.setTim(st.getTim() + st.getMsecs());
						}

						continue;
					}

					if (st.getTim() + st.getMsecs() < Time.getInstance()
							.getARXTime()) {
						ScriptObject es = st.getEs();
						InteractiveObject io = st.getIo();
						int pos = st.getPos();

						if (es == null) {
							/*
							 * if (!stricmp(st->name, "_R_A_T_")) { if
							 * (Manage_Specific_RAT_Timer(st)) continue; }
							 */
						}

						if (st.getTimes() == 1) {
							ARX_SCRIPT_Timer_ClearByNum(i);
						} else {
							if (st.getTimes() != 0) {
								st.setTimes(st.getTimes() - 1);
							}
							st.setTim(st.getTim() + st.getMsecs());
						}

						if (es != null
								&& Interactive.getInstance().ValidIOAddress(io)) {
							SendScriptEvent(
									es,
									GlobalConsts.SM_EXECUTELINE,
									"",
									io,
									null,
									pos);
						}

					}
				}
			}
		}
	}
	/**
	 * Clears all {@link ScriptTimer}s associated with a specific
	 * {@link InteractiveObject} that match the object's over script.
	 * @param io the associated {@link InteractiveObject}
	 */
	public final void ARX_SCRIPT_Timer_Clear_All_Locals_For_IO(
			final InteractiveObject io) {
		for (int i = 0; i < super.getMAX_TIMER_SCRIPT(); i++) {
			if (super.getScriptTimer(i) != null
					&& super.getScriptTimer(i).exists()
					&& super.getScriptTimer(i).getIo() != null
					&& super.getScriptTimer(i).getIo().equals(io)
					&& super.getScriptTimer(i).getEs() != null
					&& super.getScriptTimer(i).getEs()
							.equals(io.getOverScript())) {
				ARX_SCRIPT_Timer_ClearByNum(i);
			}
		}
	}
	/**
	 * Clears all {@link ScriptTimer}s associated with a specific
	 * {@link InteractiveObject}.
	 * @param io the associated {@link InteractiveObject}
	 */
	public final void ARX_SCRIPT_Timer_Clear_By_IO(final InteractiveObject io) {
		for (int i = 0; i < super.getMAX_TIMER_SCRIPT(); i++) {
			if (super.getScriptTimer(i) != null
					&& super.getScriptTimer(i).exists()
					&& super.getScriptTimer(i).getIo() != null
					&& super.getScriptTimer(i).getIo().equals(io)) {
				ARX_SCRIPT_Timer_ClearByNum(i);
			}
		}
	}
	/**
	 * Clears a {@link ScriptTimer} by its name and referenced
	 * {@link InteractiveObject}.
	 * @param timername the timer's name
	 * @param io the associated {@link InteractiveObject}
	 */
	public final void ARX_SCRIPT_Timer_Clear_By_Name_And_IO(final String timername,
			final InteractiveObject io) {
		for (int i = 0; i < super.getMAX_TIMER_SCRIPT(); i++) {
			if (super.getScriptTimer(i) != null
					&& super.getScriptTimer(i).exists()
					&& super.getScriptTimer(i).getIo() != null
					&& super.getScriptTimer(i).getIo().equals(io)
					&& super.getScriptTimer(i).getNameAsBytes() != null
					&& super.getScriptTimer(i).getNameAsString()
							.equalsIgnoreCase(
									timername)) {
				ARX_SCRIPT_Timer_ClearByNum(i);
			}
		}
	}
	/** Clears all timers. */
	public final void ARX_SCRIPT_Timer_ClearAll() {
		if (super.getActiveTimers() > 0) {
			for (int i = 0; i < super.getMAX_TIMER_SCRIPT(); i++) {
				ARX_SCRIPT_Timer_ClearByNum(i);
			}
		}
		super.setActiveTimers(0);
	}
	/**
	 * Clears a timer by its index on the timers list.
	 * @param timer_idx the timer's index
	 */
	public final void ARX_SCRIPT_Timer_ClearByNum(final int timer_idx) {
		if (super.getScriptTimer(timer_idx) != null
				&& super.getScriptTimer(timer_idx).exists()) {
			super.getScriptTimer(timer_idx).setEs(null);
			super.getScriptTimer(timer_idx).setExist(false);
			super.getScriptTimer(timer_idx).setIo(null);
			super.getScriptTimer(timer_idx).setLonginfo(0);
			super.getScriptTimer(timer_idx).setMsecs(0);
			super.getScriptTimer(timer_idx).setName(null);
			super.getScriptTimer(timer_idx).setNamelength(0);
			super.getScriptTimer(timer_idx).setPos(0);
			super.getScriptTimer(timer_idx).setTim(0);
			super.getScriptTimer(timer_idx).setTimes(0);
			super.getScriptTimer(timer_idx).clearFlags();
			super.setActiveTimers(super.getActiveTimers() - 1);
		}
	}
	/**
	 * Checks if timer named texx exists. If so returns timer index else return
	 * -1.
	 * @return int
	 */
	public final int ARX_SCRIPT_Timer_Exist(final String texx) {
		int val = -1;
		if (texx != null) {
			for (int i = 0; i < super.getMAX_TIMER_SCRIPT(); i++) {
				if (super.getScriptTimer(i) != null
						&& super.getScriptTimer(i).exists()
						&& super.getScriptTimer(i).getNameAsBytes() != null
						&& super.getScriptTimer(i).getNameAsString()
								.equalsIgnoreCase(texx)) {
					val = i;
					break;
				}
			}
		}
		return val;
	}
	/**
	 * Initialize the timer list for the first time.
	 * @param number the number of timers to initialize
	 */
	public final void ARX_SCRIPT_Timer_FirstInit(final int number) {
		super.setMAX_TIMER_SCRIPT(Math.max(100, number));
		super.initScriptTimers();
		super.setActiveTimers(0);
	}
	/**
	 * Generates a random name for an unnamed timer.
	 * @return byte[]
	 */
	public final byte[] ARX_SCRIPT_Timer_GetDefaultNameAsBytes() {
		byte[] bytes = null;
		int i = 1;
		while (true) {
			PooledStringBuilder sb =
					StringBuilderPool.getInstance().getStringBuilder();
			sb.append("TIMER_");
			sb.append(String.format("%d", i++));
			if (ARX_SCRIPT_Timer_Exist(sb.toString()) == -1) {
				bytes = sb.toString().getBytes();
				sb.returnToPool();
				break;
			}
		}
		return bytes;
	}
	/**
	 * Gets the index of a free script timer.
	 * @return int
	 */
	public final int ARX_SCRIPT_Timer_GetFree() {
		int val = -1;
		for (int i = 0; i < super.getMAX_TIMER_SCRIPT(); i++) {
			if (super.getScriptTimer(i) != null
					&& !super.getScriptTimer(i).exists()) {
				val = i;
				break;
			}
		}
		return val;
	}
}
